package election.api;


import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import election.platform.Operation;



public class Drafter implements Draft
{
    Operation spawn;
    Operation reduce;

    @Override
    public void seal() throws Exception
    {
        String[] hosts = summon();
        System.out.println(Arrays.toString(hosts));
        int index = (int)System.currentTimeMillis() % hosts.length;
        
        transferSpawn(hosts, index, spawn);
        transferReduce(hosts,index, reduce);
        System.out.println("Draft Finish");
    }
    
    
    
    @Override
    public void alter(OpMap operator, String x, String y)
    {

    }


    @Override
    public void gather(OpReduce operator, String x, String y)
    {
        reduce = new Operation(operator, x, y);
    }


    @Override
    public void spawn(OpSpawn operator, String output)
    {
        spawn = new Operation(operator, null, output);
    }
    
    protected String[] summon() throws Exception
    {
        DatagramSocket socket = new DatagramSocket(5678);
        socket.setBroadcast(true);
        socket.setSoTimeout(1000);
        
        byte[] cmd = "ReportIP".getBytes();
        DatagramPacket packet = new DatagramPacket(cmd,cmd.length,InetAddress.getByName("192.168.1.255"),9090);            
        socket.send(packet);
        Set<String> voiceBacks = new HashSet<String>();
        
        long startTime = System.currentTimeMillis();
        while (true) try {
            socket.receive(packet);
            InetAddress address = packet.getAddress();
            System.out.println("Hear from "+address.getHostName());
            voiceBacks.add(address.getHostAddress());
        } catch (Exception e) {
            long currentTime = System.currentTimeMillis();
            if (currentTime - startTime > 3000)
                break;
        }
        
        return voiceBacks.toArray(new String[0]);
    }



    private void transferReduce(String[] hosts, int index, Operation operation) throws UnknownHostException, IOException
    {
        operation.feedCount = hosts.length-1;
        Socket conn = new Socket(hosts[index],9080);
        ObjectOutputStream out = new ObjectOutputStream(conn.getOutputStream());
        out.writeObject(operation);
        conn.close();
    }



    private void transferSpawn(String[] hosts, int index, Operation operation) throws UnknownHostException, IOException
    {
        operation.nextHost = hosts[index];        // map result will be sent here
        for (String host : hosts) {
            if (host.equals(operation.nextHost)) continue;
            Socket conn = new Socket(host,9080);
            ObjectOutputStream out = new ObjectOutputStream(conn.getOutputStream());
            out.writeObject(operation);
            conn.close();
        }
    }
}



